/*
 *  mih_message.h
 *  MIHF
 *
 *  Created by injae song on 11. 3. 4..
 *  Copyright 2011 KyungHee Univ. All rights reserved.
 *
 */

#ifndef MIH_MESSAGE_H
#define MIH_MESSAGE_H

#include "list.h"
#include "mih_type.h"
#include "mih_tlv.h"
#include "mihf.h"

#include <memory.h>
#define MIH_HEADER_SIZE 8
/* Macros to set/clear/test flags. */
#define SET(t, f)       ((t) |= (f))
#define CLR(t, f)       ((t) &= ~(f))
#define ISSET(t, f)     ((t) & (f))

/*************************************
 * MIH message header structure *
 *************************************/
typedef struct mih_header
{
	unsigned version			: 4;
	unsigned ackreq				: 1;
	unsigned ackrsp				: 1;
	unsigned uir				: 1;
	unsigned morefragment		: 1;
	unsigned fragmentnumber		: 7;
	unsigned rsvd1				: 1;
	unsigned sid				: 4;
	unsigned opcode				: 2;
	unsigned aid				: 10;
	unsigned rsvd2				: 4;
	unsigned mih_tid			: 12;
	unsigned payloadlength		: 16;
	
}mih_header;



/*************************************
 * MIH Message Structure *
 *************************************/
typedef struct _mih_message {
	mih_header *header;
	List* payload; // payload
}mih_message;

typedef struct _mih_transaction_sm {
	
	enum {
		SOURCE,
		DESTINATION
	} transaction_type;
	
	enum {
		SRC_INIT,
		SRC_WAIT_RESPONSE_MSG,
		SRC_FAILURE,
		SRC_WAIT_ACK,
		SRC_PROCESS_MSG,
		SRC_SUCCESS,
		DST_INIT,
		DST_WAIT_RESPONSE_PRM,
		DST_FAILURE,
		DST_SEND_RESPONSE,
		DST_SUCCESS
	} transaction_state;
	
	enum  {
		TR_ONGOING,
		TR_SUCCESS,
		TR_FAILURE,
	} transaction_status;
	
	BOOLEAN response_received;
	
	int opcode;
	int startACKrequestor;
	int startACKresponder;
	
	enum {
		ACK_REQ_ONGOING,
		ACK_REQ_SUCCESS,
	} ACKrequestorstatus;
	
	unsigned int transactionID;
	
	mih_message *request;
	mih_message *response;
	mih_message *indication;
	
	void (*cb)(int status, mih_message*, void *);
	void *cb_arg;
	mihf *mih;
	void *peer;
}mih_transaction_sm;

/*************************************
 * MIH Message Functions *
 *************************************/


mih_message *new_mih_message(mih_sid sid, mih_opcode opcode, int aid);

mih_message* alloc_mih_message(void);

void payload_destory(void* data);

generic_tlv *new_tlv(unsigned int type, char *data, int length);

generic_tlv *alloc_tlv(int length) ;

char *generic_tlv_serialize(generic_tlv *tlv);

char *mih_message_serialize(mih_message* message);

mih_message *mih_message_parse(char *mih_frame);

void mih_message_add_tlv(mih_message* msg, generic_tlv *tlv);

generic_tlv *get_tlv(mih_message *msg, tlv_type type);

char *get_dst_mihfid(mih_message* msg);

char *get_src_mihfid(mih_message* msg);

void mih_add_dst_tlv(mih_message* msg, char* peer_id, mihf *mih);

void mih_add_local_src_tlv(mih_message* msg, mihf *mih);

#endif